#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UTable.Input.Keyboard;
using UTable.Objects;

namespace UTable.Input.Text
{
    public class KeyboardTextInputProvider: TextInputProvider
    {
        private IKeyboard _keyboard;
        private List<String> upCharList = new List<string>();
        private List<String> downCharList = new List<string>();


        private void OnKeyboardKeyPressed(KeyInputEventArgs args)
        {
            if (args.Key == Key.Escape)
            {
				TriggerInputEvent(new TextInputEventArgs(this, CheckControlCommand(args), args.Timestamp));
                UTableHelper.TextInputManager.TerminateTextInput(this.Target);
                return;
            }
            if (CheckControlCommand(args) != ControlCommand.None)
            {
                TriggerInputEvent(new TextInputEventArgs(this, CheckControlCommand(args), args.Timestamp));
                return;
            }
            String text = GetInputText(args);
            if (!String.IsNullOrEmpty(text))
                TriggerInputEvent(new TextInputEventArgs(this, text, args.Timestamp));
        }

        private String GetInputText(KeyInputEventArgs args)
        {
            bool capsLock = Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled;
            bool shiftDown = Keyboard.GetKeyStates(Key.LeftShift) == KeyStates.Down || 
                Keyboard.GetKeyStates(Key.RightShift) == KeyStates.Down;
            switch(args.Key)
            {
                case Key.A:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "A" : "a";
                case Key.B:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "B" : "b";
                case Key.C:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "C" : "c";
                case Key.D:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "D" : "d";
                case Key.E:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "E" : "e";
                case Key.F:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "F" : "f";
                case Key.G:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "G" : "g";
                case Key.H:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "H" : "h";
                case Key.I:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "I" : "i";
                case Key.J:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "J" : "j";
                case Key.K:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "K" : "k";
                case Key.L:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "L" : "l";
                case Key.M:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "M" : "m";
                case Key.N:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "N" : "n";
                case Key.O:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "O" : "o";
                case Key.P:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "P" : "p";
                case Key.Q:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "Q" : "q";
                case Key.R:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "R" : "r";
                case Key.S:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "S" : "s";
                case Key.T:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "T" : "t";
                case Key.U:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "U" : "u";
                case Key.V:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "V" : "v";
                case Key.W:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "W" : "w";
                case Key.X:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "X" : "x";
                case Key.Y:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "Y" : "y";
                case Key.Z:
                    return capsLock && !shiftDown || !capsLock && shiftDown ? "Z" : "z";
                case Key.OemTilde:
                    return shiftDown ? "~" : "`";
                case Key.D1:
                    return shiftDown ? "!" : "1";
                case Key.D2:
                    return shiftDown ? "@" : "2";
                case Key.D3:
                    return shiftDown ? "#" : "3";
                case Key.D4:
                    return shiftDown ? "$" : "4";
                case Key.D5:
                    return shiftDown ? "%" : "5";
                case Key.D6:
                    return shiftDown ? "^" : "6";
                case Key.D7:
                    return shiftDown ? "&" : "7";
                case Key.D8:
                    return shiftDown ? "*" : "8";
                case Key.D9:
                    return shiftDown ? "(" : "9";
                case Key.D0:
                    return shiftDown ? ")" : "0";
                case Key.OemMinus:
                    return shiftDown ? "_" : "-";
                case Key.OemPlus:
                    return shiftDown ? "+" : "=";
                case Key.OemOpenBrackets:
                    return shiftDown ? "{" : "[";
                case Key.OemCloseBrackets:
                    return shiftDown ? "}" : "]";
                case Key.OemBackslash:
                    return shiftDown ? "|" : "\\";
                case Key.OemSemicolon:
                    return shiftDown ? ":" : ";";
                case Key.OemQuotes:
                    return shiftDown ? "\"" : "'";
                case Key.OemComma:
                    return shiftDown ? "<" : ",";
                case Key.OemPeriod:
                    return shiftDown ? ">" : ".";
                case Key.OemQuestion:
                    return shiftDown ? "?" : "/";
                case Key.Space:
                    return " ";
                case Key.Tab:
                    return "\t";
                case Key.Enter:
                    return "\n";

            }
            return "";
        }

        private ControlCommand CheckControlCommand(KeyInputEventArgs args)
        {
            switch (args.Key)
            {
                case Key.Back:
                    return ControlCommand.Back;
                case Key.Cancel:
                    return ControlCommand.Cancel;
                case Key.Clear:
                    return ControlCommand.Clear;
                case Key.Pause:
                    return ControlCommand.Pause;
                case Key.Escape:
                    return ControlCommand.Escape;
                case Key.PageUp:
                    return ControlCommand.PageUp;
                case Key.PageDown:
                    return ControlCommand.PageDown;
                case Key.End:
                    return ControlCommand.End;
                case Key.Home:
                    return ControlCommand.Home;
                case Key.Left:
                    return ControlCommand.Left;
                case Key.Right:
                    return ControlCommand.Right;
                case Key.Up:
                    return ControlCommand.Up;
                case Key.Down:
                    return ControlCommand.Down;
                case Key.Select:
                    return ControlCommand.Select;
                case Key.Print:
                    return ControlCommand.Print;
                case Key.Execute:
                    return ControlCommand.Execute;
                case Key.Insert:
                    return ControlCommand.Insert;
                case Key.Delete:
                    return ControlCommand.Delete;
                case Key.Help:
                    return ControlCommand.Help;
            }
            return ControlCommand.None;
        }

        private void TriggerInputEvent(TextInputEventArgs args)
        {
            if (InputTriggered != null)
                InputTriggered(args);
        }

        private void OnKeyboardKeyDown(KeyInputEventArgs args)
        {
        }

        private void OnKeyboardKeyUp(KeyInputEventArgs args)
        {
        }

        public override UTable.Objects.IVisualNode Target
        {
            get
            {
                return base.Target;
            }
            set
            {
                base.Target = value;
            }
        }

        public KeyboardTextInputProvider(IKeyboard keyboard, String name): base(name)
        {
            Keyboard = keyboard;
        }

        public IKeyboard Keyboard
        {
            get
            {
                return _keyboard;
            }
            set
            {
                if (_keyboard != null)
                {
                    _keyboard.KeyUp -= OnKeyboardKeyUp;
                    _keyboard.KeyDown -= OnKeyboardKeyDown;
                    _keyboard.KeyPressed -= OnKeyboardKeyPressed;
                }
                _keyboard = value;
                _keyboard.KeyUp += OnKeyboardKeyUp;
                _keyboard.KeyDown += OnKeyboardKeyDown;
                _keyboard.KeyPressed += OnKeyboardKeyPressed;
            }
        }

        public override event InputEventHandler InputTriggered;
    }
}
